package com.qiaofang.applet.service.property.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.common.context.QfContext;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.applet.common.util.RedisKeyUtil;
import com.qiaofang.applet.common.util.RedisUtil;
import com.qiaofang.applet.constants.HouseTypeConstants;
import com.qiaofang.applet.constants.PhotoCategoryConstants;
import com.qiaofang.applet.service.other.domain.CityCompany;
import com.qiaofang.applet.service.other.domain.PropertyWaterMark;
import com.qiaofang.applet.service.other.repository.CityCompanyRepository;
import com.qiaofang.applet.service.property.domain.*;
import com.qiaofang.applet.service.property.repository.EstateAlbumRepository;
import com.qiaofang.applet.service.property.repository.EstateDetailRepository;
import com.qiaofang.applet.service.property.repository.EstatePhotoRepository;
import com.qiaofang.applet.service.property.repository.EstateRepository;
import com.qiaofang.applet.service.property.service.*;
import com.qiaofang.applet.service.property.service.dto.*;
import com.qiaofang.applet.service.property.service.mapstruct.EstateDetailMapper;
import com.qiaofang.applet.service.property.service.mapstruct.EstateMapper;
import com.qiaofang.applet.service.property.service.mapstruct.EstatePhotoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
//import java.util.*;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EstateDetailServiceImpl extends MongoBaseService<EstateDetail, String> implements EstateDetailService {

    private final EstateDetailRepository repository;

    @Autowired
    private EstateDetailRepository estateDetailRepository;

    @Autowired
    private EstatePhotoRepository estatePhotoRepository;

    @Autowired
    private EstateAlbumRepository estateAlbumRepository;

    @Autowired
    private EstateRepository estateRepository;

    @Autowired
    private EstateMapper estateMapper;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private EstateDetailMapper estateDetailMapper;

    @Autowired
    private EstateHouseTypeFyService estateHouseTypeFyService;

    @Autowired
    private EstatePhotoMapper estatePhotoMapper;

    @Autowired
    private EstateService estateService;

    @Autowired
    private EstateAlbumPhotoService estateAlbumPhotoService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private CityCompanyRepository cityCompanyRepository;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    public EstateDetailServiceImpl(EstateDetailRepository repository) {
        super(repository);
        this.repository = repository;
    }


    /**
     * 后台管理系统获取小区编辑页信息
     *
     * @param estateUniqueUuid
     * @return
     */
    @Override
    public EstateEditDto getEstateEditDetail(String estateUniqueUuid) {
        Estate estate = estateRepository.findByEstateUniqueUuid(estateUniqueUuid);
        if (estate == null) {
            throw new BusinessException("未能获取楼盘数据");
        }
        EstateDetail estateDetail = estateDetailRepository.findByEstateUniqueUuid(estateUniqueUuid);

        EstateEditDto estateEditDto;
        if (estateDetail != null) {
            estateEditDto = estateDetailMapper.domainToEditDto(estateDetail);
        } else {
            estateEditDto = estateDetailMapper.domainToDto(estate);
        }
        //封面图
        estateEditDto.setPhotoUrl(estate.getPhotoUrl());
        estateEditDto.setEstateName(estate.getEstateName());
        estateEditDto.setTypeFyMap(getHouseTypeMap(estateUniqueUuid));

        List<EstateAlbum> estateAlbumList = estateAlbumRepository.findAllByEstateUniqueUuid(estateUniqueUuid);
        //相册数量
        estateEditDto.setPhotoAlbumNum(estateAlbumList == null ? 0 : estateAlbumList.size());
        //点评数量
        if (estateDetail == null) {
            estateEditDto.setCommentNum(0);
        } else {
            estateEditDto.setCommentNum(estateDetail.getEstateComments() == null ? 0 : estateDetail.getEstateComments().size());
        }
        return estateEditDto;
    }

    private Map<String, List<HouseTypeDto>> getHouseTypeMap(String estateUniqueUuid) {
        Map<String, List<HouseTypeDto>> typeFyMap = new HashMap<>();
        List<HouseTypeDto> twoList = new LinkedList<>();
        List<HouseTypeDto> threeList = new LinkedList<>();
        List<HouseTypeDto> fourList = new LinkedList<>();
        List<HouseTypeDto> fiveList = new LinkedList<>();
        //查询楼盘户型图列表
        List<EstatePhoto> photoList = estatePhotoRepository.findAllByEstateUniqueUuidAndCategoryName(estateUniqueUuid, "fangxing");

        if (!CollectionUtils.isEmpty(photoList)) {
            for (EstatePhoto photo : photoList) {
                HouseTypeDto houseTypeDto = estatePhotoMapper.domainToDto(photo);
                houseTypeDto.setHouseType(houseTypeDto.getHouseType());
                EstatePropertyQueryDto estatePropertyQueryDto = new EstatePropertyQueryDto();
                estatePropertyQueryDto.setCountF(photo.getCountF());
                estatePropertyQueryDto.setQueryFlag(1);
                estatePropertyQueryDto.setPhotoUuid(photo.getPhotoUuid());
                estatePropertyQueryDto.setEstateUniqueUuid(photo.getEstateUniqueUuid());

                //根据图片uuid查询当前对应户型图
                EstateHouseTypeCountDto houseTypeCount = estateHouseTypeFyService.getHouseTypeCount(photo.getEstateUniqueUuid(), photo.getPhotoUuid());
                houseTypeDto.setRentNum(houseTypeCount.getRentNum());
                houseTypeDto.setSaleNum(houseTypeCount.getSaleNum());

                if (photo.getCountF() == null || photo.getCountF() <= 2) {
                    twoList.add(houseTypeDto);
                } else if (photo.getCountF() == 3) {
                    threeList.add(houseTypeDto);
                } else if (photo.getCountF() == 4) {
                    fourList.add(houseTypeDto);
                } else {
                    fiveList.add(houseTypeDto);
                }
            }
        }
        PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        for (HouseTypeDto typeDto : twoList) {
            typeDto.setPhotoURL(commonService.propertyWaterMark(typeDto.getPhotoURL(), propertyWaterMark));
        }

        for (HouseTypeDto typeDto : threeList) {
            typeDto.setPhotoURL(commonService.propertyWaterMark(typeDto.getPhotoURL(), propertyWaterMark));
        }

        for (HouseTypeDto typeDto : fourList) {
            typeDto.setPhotoURL(commonService.propertyWaterMark(typeDto.getPhotoURL(), propertyWaterMark));
        }

        for (HouseTypeDto typeDto : fiveList) {
            typeDto.setPhotoURL(commonService.propertyWaterMark(typeDto.getPhotoURL(), propertyWaterMark));
        }


        typeFyMap.put(HouseTypeConstants.TWO_ROOM.getValue(), twoList);
        typeFyMap.put(HouseTypeConstants.THREE_ROOM.getValue(), threeList);
        typeFyMap.put(HouseTypeConstants.FOUR_ROOM.getValue(), fourList);
        typeFyMap.put(HouseTypeConstants.FIVE_ROOM.getValue(), fiveList);
        return typeFyMap;
    }

    /**
     * 保存小区详情 后台管理系统调用
     *
     * @param estateEditDto
     */
    @Override
    public void saveEstateDetail(EstateEditDto estateEditDto) {
        EstateDetail estateDetail = estateDetailMapper.editDtoToDomain(estateEditDto);
        EstateDetail oldEstateDetail = repository.findByEstateUniqueUuid(estateEditDto.getEstateUniqueUuid());
        if (oldEstateDetail != null && oldEstateDetail.getId() != null) {
            estateDetail.setId(oldEstateDetail.getId());
            //因为小区点评可以单独保存，且没有关联，
            //所以在保存小区详情的时候需要在原先单独保存的，把数据带出来
            estateDetail.setEstateComments(oldEstateDetail.getEstateComments());
        }
        repository.save(estateDetail);
    }

    /**
     * 客户端获取小区详情
     *
     * @param estateUniqueUuid
     * @return
     */
    @Override
    public EstateShowDto getEstateShowDto(String estateUniqueUuid, String version) {
        Estate estate = estateRepository.findByEstateUniqueUuid(estateUniqueUuid);
        if (estate == null) {
            throw new BusinessException("楼盘数据不存在");
        }
        EstateShowDto estateShowDto = estateMapper.domainToShowDto(estate);
        EstateDetail estateDetail = repository.findByEstateUniqueUuid(estateUniqueUuid);
        if (estateDetail != null) {
            estateShowDto.setCurrentRentPrice(estateDetail.getCurrentRentPrice());
            estateShowDto.setCurrentSellPrice(estateDetail.getCurrentSellPrice());
            estateShowDto.setIntroduction(estateDetail.getIntroduction());
            estateShowDto.setDriveCircuit(estateDetail.getDriveCircuit());
            estateShowDto.setSurroundingExplain(estateDetail.getSurroundingExplain());
            estateShowDto.setHouseTypeDes(estateDetail.getHouseTypeDes());
            estateShowDto.setDwellCrowd(estateDetail.getDwellCrowd());
            estateShowDto.setDwellDes(estateDetail.getDwellDes());
            if (!CollectionUtils.isEmpty(estateDetail.getStoryList())){
                estateShowDto.setStoryList(estateDetail.getStoryList().stream().sorted(Comparator.comparing(EstateStory::getDate).reversed()).collect(Collectors.toList()));
            }
            estateShowDto.setUnfold(estateDetail.getUnfold());
        }
        if (estateShowDto.getSellPrice() == null){
            estateShowDto.setSellPrice(new BigDecimal("0.0"));
        }
        if (estateShowDto.getCurrentRentPrice() == null){
            estateShowDto.setCurrentRentPrice(new BigDecimal("0.0"));
        }
        if (estateShowDto.getCurrentSellPrice() == null){
            estateShowDto.setCurrentSellPrice(new BigDecimal("0.0"));
        }
        if (estateShowDto.getOwnYear() == null){
            estateShowDto.setOwnYear(0);
        }
        if (estateShowDto.getTotalRoomCount() == null){
            estateShowDto.setTotalRoomCount(0);
        }
        estateShowDto.setTypeFyMap(getHouseTypeMap(estateUniqueUuid));
        List<String> mappedResults = getOuterPhotoList(estateUniqueUuid, estate.getCompanyUuid());
        estateShowDto.setOuterPhotoList(mappedResults);
        if (org.apache.commons.lang3.StringUtils.equals("newVersion", version)) {
            List<EstateDetailsPhotoDto> estatePhoto = getEstatePhoto(estateUniqueUuid);
            if (!CollectionUtils.isEmpty(estatePhoto)) {
                estateShowDto.setEstateDetailsPhotoDtos(estatePhoto);
            }
        } else {
            List<String> albumPhotoList = getAlbumPhotoList(estateUniqueUuid);
            estateShowDto.setAlbumPhotoNum(albumPhotoList.size());
            if (!CollectionUtils.isEmpty(albumPhotoList)) {
                estateShowDto.setAlbumPhotoShow(albumPhotoList.get(0));
            }
        }
        //周边小区推荐
        List<EstateListDto> surroundingEstates = getSurroundingEstates(estate.getCityCode(), estate.getDistrictUuid(), estateUniqueUuid);
        estateShowDto.setSurroundingEstates(surroundingEstates);
        return estateShowDto;
    }

    /**
     * 获取当前小区照片
     * @param estateUniqueUuid
     * @return
     */
    private List<EstateDetailsPhotoDto> getEstatePhoto(String estateUniqueUuid){
        List<EstateDetailsPhotoDto> estateDetailsPhotoDtos = null;
        try {
            List<EstateAlbumDto> collectList = Optional.ofNullable(estateAlbumPhotoService.getAlbums(estateUniqueUuid)).orElseGet(Lists::newArrayList)
                    .stream().sorted(Comparator.comparing(EstateAlbumDto::getSort)).collect(Collectors.toList());

            //当前小区相册list
            estateDetailsPhotoDtos = estatePhotoMapper.dtoListToDtoList(collectList);
            //相册ids
            List<String> idList = estateDetailsPhotoDtos.stream().map(EstateDetailsPhotoDto::getId).distinct().collect(Collectors.toList());
            Query query = new Query(Criteria.where("albumId").in(idList));
            List<EstateAlbumPhoto> resultList = Optional.ofNullable(mongoTemplate.find(query, EstateAlbumPhoto.class)).orElseGet(Lists::newArrayList)
                    .stream().collect(
                            Collectors.collectingAndThen(
                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(EstateAlbumPhoto::getAlbumId))),
                                    dto -> new ArrayList<>(dto)));

            for (EstateDetailsPhotoDto estateDetailsPhotoDto : estateDetailsPhotoDtos) {
                for (EstateAlbumPhoto photo : resultList) {
                    if (photo.getAlbumId().equals(estateDetailsPhotoDto.getId())){
                        estateDetailsPhotoDto.setAlbumPhotoShow(photo.getPhotoURL());
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取当前小区失败 ：{}", e);
        }
        return estateDetailsPhotoDtos;
    }

    private List<String> getOuterPhotoList(String estateUniqueUuid, String companyUuid) {
        String propertyWaterMarkKey = RedisKeyUtil.getPropertyWaterMarkKey(companyUuid);
        Object obj = redisUtil.hget(propertyWaterMarkKey, estateUniqueUuid);
        if (obj != null) {
            return JSONObject.parseArray(JSONObject.toJSONString(obj), String.class);
        }
        List<String> outerPhotoList = new LinkedList<>();
        List<EstatePhoto> categoryName = estatePhotoRepository.findAllByEstateUniqueUuidAndCategoryName(estateUniqueUuid, PhotoCategoryConstants.OUTDOOR_PHOTO.getCategory());
        PropertyWaterMark propertyWaterMark = getPropertyWaterMark();
        for (EstatePhoto estatePhoto : categoryName) {
            outerPhotoList.add(commonService.propertyWaterMark(estatePhoto.getPhotoURL(), propertyWaterMark));
        }
        redisUtil.hset(propertyWaterMarkKey, estateUniqueUuid ,outerPhotoList);
        return outerPhotoList;
    }

    private List<String> getAlbumPhotoList(String estateUniqueUuid) {
        List<String> albumPhotoList = new LinkedList<>();
        List<EstateAlbum> albums = estateAlbumRepository.findAllByEstateUniqueUuid(estateUniqueUuid);
        if (!CollectionUtils.isEmpty(albums)){
            List<String> ids = new ArrayList<>(albums.size());
            for (EstateAlbum album : albums) {
                ids.add(album.getId());
            }
            Query query = new Query();
            query.addCriteria(Criteria.where("albumId").in(ids));
            List<EstateAlbumPhoto> albumPhotos = mongoTemplate.find(query, EstateAlbumPhoto.class);
            if (!CollectionUtils.isEmpty(albumPhotos)){
                for (EstateAlbumPhoto albumPhoto : albumPhotos) {
                    albumPhotoList.add(albumPhoto.getPhotoURL());
                }
            }
        }
        return albumPhotoList;
    }


    private List<EstateListDto> getSurroundingEstates(String cityCode, String districtUuid, String estateUniqueUuid) {
        if (StringUtils.isEmpty(districtUuid)){
            return new ArrayList<>();
        }
        EstateQueryDto estateQueryDto = new EstateQueryDto();
        estateQueryDto.setAreaUuid(districtUuid);
        estateQueryDto.setCityCode(cityCode);
        Page<Estate> page = estateService.getSurroundingEstates(estateQueryDto, estateUniqueUuid, PageRequest.of(0, 4));
        return estateService.convertDomainToEstateListDto(page.getContent());
    }

    @Override
    public List<EstateCommentDto> getEstateComment(String estateUniqueUuid) {
        EstateDetail estateDetail = repository.findByEstateUniqueUuid(estateUniqueUuid);

        if (estateDetail == null) {
            return new ArrayList<>();
        }

        List<EstateComment> collectList = Optional.ofNullable(estateDetail.getEstateComments()).orElseGet(Lists::newArrayList)
                .stream().sorted(Comparator.comparing(EstateComment::getSort)).collect(Collectors.toList());
        return estateMapper.dtoListToDtoList(collectList);
    }

    @Override
    public List<EstateCommentAdminDto> listEstateComment(String estateUniqueUuid) {
        EstateDetail estateDetail = repository.findByEstateUniqueUuid(estateUniqueUuid);
        if (estateDetail == null) {
           return new ArrayList<>();
        }
        List<EstateComment> collectList = Optional.ofNullable(estateDetail.getEstateComments()).orElseGet(Lists::newArrayList)
                .stream().sorted(Comparator.comparing(EstateComment::getCreateTime)).collect(Collectors.toList());
        return estateMapper.domainListToDtoList(collectList);
    }

    @Override
    public void addEstateComment(EstateCommentAddDto estateCommentAddDto) {
        EstateDetail estateDetail = repository.findByEstateUniqueUuid(estateCommentAddDto.getEstateUniqueUuid());
        //第一次操作,单独添加评论
        if (estateDetail == null) {
            Estate estate = estateService.findByEstateUniqueUuid(estateCommentAddDto.getEstateUniqueUuid());
            if (estate == null){
                throw new BusinessException("楼盘不存在");
            }
            EstateEditDto estateEditDto = estateDetailMapper.domainToDto(estate);
            EstateComment estateComment = estateDetailMapper.addDtoToAdmin(estateCommentAddDto);
            estateEditDto.setEstateComment(estateComment);
            saveEstateComment(estateEditDto);
        } else {
            List<EstateComment> estateComments = estateDetail.getEstateComments();
            if (CollectionUtils.isEmpty(estateComments)) {
                estateComments = new ArrayList<>();
            }
            if (org.apache.commons.lang3.StringUtils.isBlank(estateCommentAddDto.getId())) {
                //新增
                EstateComment estateComment = estateDetailMapper.addDtoToAdmin(estateCommentAddDto);
                estateComments.add(estateComment);
            } else {
                //修改
                EstateComment estateComment = estateComments.stream().filter(f -> org.apache.commons.lang3.StringUtils.equals(estateCommentAddDto.getId(), f.getId())).findFirst().get();
                estateComment.setSort(org.apache.commons.lang3.StringUtils.defaultString(estateCommentAddDto.getSort(), estateComment.getSort()));
                estateComment.setOwnerName(org.apache.commons.lang3.StringUtils.defaultString(estateCommentAddDto.getOwnerName(), estateComment.getOwnerName()));
                estateComment.setCommentContent(org.apache.commons.lang3.StringUtils.defaultString(estateCommentAddDto.getCommentContent(), estateComment.getCommentContent()));
                for (EstateComment comment : estateComments) {
                    if (org.apache.commons.lang3.StringUtils.equals(estateCommentAddDto.getId(), comment.getId())) {
                        estateComments.remove(comment);
                        break;
                    }
                }
                estateComments.add(estateComment);
            }
            estateDetail.setEstateComments(estateComments);
            updateById(estateDetail);
        }
    }

    @Override
    public void deleteEstateComment(EstateCommentDeleteDto deleteDto) {
        EstateDetail estateDetail = repository.findByEstateUniqueUuid(deleteDto.getEstateUniqueUuid());
        if (estateDetail == null) {
            throw new BusinessException("楼盘详情不存在");
        }
        List<EstateComment> estateComments = estateDetail.getEstateComments();
        for (EstateComment estateComment : estateComments) {
            if (org.apache.commons.lang3.StringUtils.equals(estateComment.getId(), deleteDto.getId())) {
                estateComments.remove(estateComment);
                break;
            }
        }
        estateDetail.setEstateComments(estateComments);
        updateById(estateDetail);
    }

    private void saveEstateComment(EstateEditDto estateEditDto){
        EstateDetail estateDetail = estateDetailMapper.editDtoToDomain(estateEditDto);
        estateDetail.setEstateComments(Lists.newArrayList(estateEditDto.getEstateComment()));
        EstateDetail oldEstateDetail = repository.findByEstateUniqueUuid(estateEditDto.getEstateUniqueUuid());
        if (oldEstateDetail != null && oldEstateDetail.getId() != null) {
            estateDetail.setId(oldEstateDetail.getId());
        }
        repository.save(estateDetail);
    }

    @Override
    public EstateDetail getEstateDetailByUuid(String estateUniqueUuid) {
        return repository.findByEstateUniqueUuid(estateUniqueUuid);
    }

    /**
     * 获取公司水印设置
     * @return
     */
    private PropertyWaterMark getPropertyWaterMark() {
        QfContext context = QfContextHolder.getContext();
        List<CityCompany> cityCompanyList = cityCompanyRepository.findAllByCorporationCodeAndCityCodeAndMainCityFlag(context.getCorporationCode(), context.getCityCode(), 1);
        if (CollectionUtils.isEmpty(cityCompanyList)) {
            return null;
        }
        return cityCompanyList.get(0).getPropertyWaterMark();
    }
}
